﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using WebApp.Common;
using WebApp.Controllers;

namespace WebApp.Extensions
{
    public static class HtmlExtensions
    {
        public static string GetAssemblyVersion(this HtmlHelper helper)
        {
            return Assembly.GetAssembly(typeof(SmartController)).GetName().Version.ToString();
        }

        public static bool IsCurrentAction(this HtmlHelper helper, string actionName, string controllerName)
        {
            var currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
            var currentActionName = (string)helper.ViewContext.RouteData.Values["action"];

            return currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase);
        }

        public static string AccessibleCheckBox(this HtmlHelper helper, string checkboxName, string checkboxLabel, bool isChecked)
        {
            var isCheckedHtml = isChecked ? "checked=\"checked\"" : string.Empty;
            var inputHtml = string.Format("<input type=\"checkbox\" value=\"true\" {0} name=\"{1}\" id=\"{1}\"/>",
                                          isCheckedHtml, checkboxName);
            var labelHtml = string.Format("<label for=\"{0}\">{1}</label>", checkboxName, checkboxLabel);
            return inputHtml + labelHtml;
        }

        public static bool ShouldPropertyBeDisplayed(PropertyInfo info)
        {
            return info.CanRead && info.PropertyType != typeof(Guid) && info.PropertyType != typeof(Guid?);
        }

        public static Expression<Func<T, object>> ProperyToLamdaExpression<T>(PropertyInfo info)
        {
            var param = Expression.Parameter(typeof(T), "arg");
            var member = Expression.Property(param, info);
            var loselyTypeExpression = Expression.Convert(member, typeof(object));
            return Expression.Lambda<Func<T, object>>(loselyTypeExpression, param);
        }

        public static IHtmlString ToJson(this HtmlHelper helper, object obj)
        {
            var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
            settings.Converters.Add(new JavaScriptDateTimeConverter());
            return helper.Raw(JsonConvert.SerializeObject(obj, settings));
        }

        /* The combination of these 2 methods enables functionality like @section in partial */
        // NOTE: Use Only For Razor Partials... for non-partial cshtml files use razor's native @section
        public static MvcHtmlString Scripts(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
        {
            htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
            return MvcHtmlString.Empty;
        }

        public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
        {
            foreach (var template in (from object key in htmlHelper.ViewContext.HttpContext.Items.Keys where key.ToString().StartsWith("_script_") select htmlHelper.ViewContext.HttpContext.Items[key]).OfType<Func<object, HelperResult>>())
            {
                htmlHelper.ViewContext.Writer.Write(template(null));
            }
            return MvcHtmlString.Empty;
        }

        public static MvcHtmlString ContactPicker(this HtmlHelper helper, string tag)
        {
            var html = @"
				<button type='button' data-toggle='modal' class='btn btn-primary' data-bind=""click: function() { $.publish('ContactPicker:showPicker', ['" + tag + @"'])}"">
					<i class='icon icon-plus'></i>
				</button>
			";
            return MvcHtmlString.Create(html);
        }

        public static MvcHtmlString AttachmentPicker(this HtmlHelper helper, string tag = null)
        {
            const string html = @"
				<button type='button' data-toggle='modal' class='btn btn-primary' data-bind=""click: function() { $('#inputFile').click(); }"">
					<i class='icon icon-plus'></i>
				</button>
			";
            return MvcHtmlString.Create(html);
        }

        public static MvcHtmlString AccountPicker(this HtmlHelper helper, string tag)
        {
            var html = @"
				<button type='button' data-toggle='modal' class='btn btn-primary' data-bind=""click: function() { $.publish('AccountPicker:showPicker', ['" + tag + @"'])}"">
					<i class='icon icon-plus'></i>
				</button>
			";
            return MvcHtmlString.Create(html);
        }

        public static MvcHtmlString ActionLinkForPage(this HtmlHelper helper, PageSetting page, PageSetting current)
        {
            var html = string.Format("<a href=\"{0}\" active-link=\"{1}\">{2}</a>", page.LinkUrl, page.LinkName == current.ActiveLink, page.LinkName);
            return MvcHtmlString.Create(html);
        }

        public static MvcHtmlString PagePathList(this HtmlHelper helper, PageSetting pageSetting)
        {
            /*
             * <ul class="breadcrumb">
                    <li><a href="#">Home</a></li>
                    <li class="active">Pages</li>
                </ul>
             */
            var html = "<ul class=\"breadcrumb\">";

            foreach (var link in pageSetting.PathLinks)
            {
                html += string.Format("<li><a href=\"{0}\">{1}</a></li>", link.LinkUrl, link.LinkName);
            }

            html += string.Format("<li class=\"active\">{0}</a></li>", pageSetting.LinkName);
            html += "</ul>";
            
            return MvcHtmlString.Create(html);
        }
    }
}
